package com.yjb.tenet.boot.framework.mybatis.plus.core.datascope;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import com.yjb.tenet.boot.framework.mybatis.plus.core.enums.DataScopeEnum;
import com.yjb.tenet.boot.framework.satoken.core.LoginUser;
import com.yjb.tenet.boot.framework.satoken.core.utils.SecurityFrameworkUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.HexValue;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;

import java.util.Set;

/**
 * @description 
 * @author yinjinbiao
 * @create 2022/5/30 10:02
 * @version 1.0
 */
@Slf4j
public class DataScopePermissionHandler implements DataPermissionHandler {

	@SneakyThrows
	@Override
	public Expression getSqlSegment(Expression where, String mappedStatementId) {
		DataScope dataScope = DataScopeContextHolder.getContext();
		if(ObjectUtil.isNull(dataScope)){
			// 未加注解不过滤
			return where;
		}
		// 取出当前登录人员
		LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();

		// 其它情况
		StringBuilder sqlString = new StringBuilder();
		Set<String> dataScopes = loginUser.getDataScopes();
		if(CollectionUtil.isEmpty(dataScopes)){
			// 初始没设置任何数据权限，默认本人
			sqlString.append(StrUtil.format(" OR {}user_id = {} ", dataScope.userAlias(), loginUser.getId()));
			return where;
		}
		if(dataScopes.contains(DataScopeEnum.DATA_SCOPE_ALL.getValue())){
			// 如果是超管，拥有全部数据权限，不过滤数据，直接返回
			return where;
		}else {
			// 否则需要过滤拥有的部门权限
			if(CollectionUtil.isNotEmpty(loginUser.getDataScopesDeptIds())){
				sqlString.append(StrUtil.format(" OR {}dept_id in ({})", dataScope.deptAlias(), StrUtil.join("," ,loginUser.getDataScopesDeptIds())));
			}
			if(dataScopes.contains(DataScopeEnum.DATA_SCOPE_SELF.getValue())){
				sqlString.append(StrUtil.format(" OR {}user_id = {} ", dataScope.userAlias(), loginUser.getId()));
			}
		}
		if(ObjectUtil.isNull(where)){
			where = new HexValue(" 1 = 1 ");
		}
		if(StrUtil.isNotBlank(sqlString.toString())){
			// 如果拼接不为空，删除第一个 OR
			String dataScopeSQL = sqlString.substring(3);
			Expression expression = CCJSqlParserUtil.parseCondExpression(dataScopeSQL);
			return new AndExpression(where, new Parenthesis(expression));
		}
		return where;
	}

}
